home *** CD-ROM | disk | FTP | other *** search
/ START Magazine / START VOL 3 NO 7.st / KAMIKAZE.ARC / MOVES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-14  |  9.8 KB  |  585 lines

  1.  
  2. #include "kamikaze.h"
  3.  
  4.  
  5. struct move *history[HSZ];
  6. ushort move_count;
  7. int living[2];
  8. WORD move_color = WHITE;
  9.  
  10. int kings_row[2] = {0, 7};
  11. int enp_row[2] = {5, 2};
  12.  
  13. backup2()
  14. {
  15. register Move *m;
  16. int i;
  17.  
  18. if (move_count < 2)
  19.     return;
  20. i = 2;
  21. while (--i >= 0)
  22.     {
  23.     m = history[move_count-1];
  24.     unboard_move(m);
  25.     freemem(m);
  26.     }
  27. find_legal_moves();
  28. hide_mouse();
  29. draw_board();
  30. show_mouse();
  31. }
  32.  
  33. unboard_move(m)
  34. register Move *m;
  35. {
  36. register char c;
  37. register struct piece *p;
  38. register int x, y;
  39.  
  40. if (move_count <= 0)    /* Shouldn't happen... */
  41.     {
  42.     puts("error - going before beginning");
  43.     return;
  44.     }
  45. move_color ^= 1;
  46.  
  47. /* find current square and  remove piece from that square */
  48. p = m->piece;
  49. x = p->column;
  50. y = p->row;
  51. board[y][x].piece = NULL;
  52.  
  53. /* move piece and put it on new place in board */
  54. x -= m->dx;
  55. y -= m->dy;
  56. p->column = x;
  57. p->row = y;
  58. p->move_count-=1;
  59. board[y][x].piece = p;
  60.  
  61. /* check castling */
  62. if (m->flags & MCASTLING)
  63.     {
  64.     y = kings_row[move_color];
  65.     if (m->dx > 0)    /* queens side? */
  66.         {
  67.         p += 4;    /* piece goes from king to queen's rook */
  68.         board[y][4].piece = NULL;    /* remove rook from middle */
  69.         board[y][7].piece = p;
  70.         p->column = 7;
  71.         }
  72.     else
  73.         {
  74.         p -= 3;    /* goes from king to king's rook */
  75.         board[y][2].piece = NULL;    /* remove rook from king's side */
  76.         board[y][0].piece = p;
  77.         p->column = 0;
  78.         }
  79.     p->move_count-=1;
  80.     }
  81. if (m->flags & MQUEENING)
  82.     {
  83.     repawn(p);
  84.     }
  85.  
  86. /* If a piece was took flag it alive again and put it on board where it
  87.    last was */
  88. if ((p = m->took_piece) != NULL)
  89.     {
  90.     living[1-move_color]+=1;
  91.     p->flags &= ~PDEAD;
  92.     board[p->row][p->column].piece = p;
  93.     }
  94.  
  95. /* update move history and toggle move color */
  96. move_count -= 1;
  97. }
  98.  
  99. board_move(m)
  100. register Move *m;
  101. {
  102. register char c;
  103. register struct piece *p;
  104. register struct square *sq;
  105. register int x, y;
  106.  
  107. /* If a piece was took flag it dead and remove from board */
  108. if ((p = m->took_piece) != NULL)
  109.     {
  110.     living[1-move_color]-=1;
  111.     p->flags |= PDEAD;
  112.     board[p->row][p->column].piece = NULL;
  113.     }
  114.  
  115. /* find current square and remove piece from that square */
  116. p = m->piece;
  117. x = p->column;
  118. y = p->row;
  119. board[y][x].piece = NULL;
  120.  
  121. /* move piece and put it on new place in board */
  122. x += m->dx;
  123. y += m->dy;
  124. p->column = x;
  125. p->row = y;
  126. board[y][x].piece = p;
  127. p->move_count += 1;
  128.  
  129. /* check castling */
  130. if (m->flags & MCASTLING)
  131.     {
  132.     y = kings_row[move_color];
  133.     if (m->dx > 0)    /* queens side? */
  134.         {
  135.         p += 4;    /* p points to queen's rook */
  136.         board[y][7].piece = NULL;    /* remove from corner */
  137.         board[y][4].piece = p;        /* put next to king */
  138.         p->column = 4;
  139.         }
  140.     else
  141.         {
  142.         p -= 3;    /* p points to king's rook */
  143.         board[y][0].piece = NULL;    /* remove from corner */
  144.         board[y][2].piece = p;        /* put next to king */
  145.         p->column = 2;
  146.         }
  147.     p->move_count += 1;
  148.     }
  149. if (m->flags & MQUEENING)
  150.     {
  151.     retype_piece(p, m->promotion);
  152.     }
  153. move_color ^= 1;
  154. if (move_count < HSZ)
  155.     {
  156.     history[move_count] = m;
  157.     move_count++;
  158.     }
  159. else
  160.     {
  161.     puts("Too many moves!");
  162.     return(0);
  163.     }
  164. return(1);
  165. }
  166.  
  167. Move *
  168. make_legal_move(p, ncol, nrow)
  169. register Piece *p;
  170. WORD ncol, nrow;
  171. {
  172. struct move m, *mpt;
  173. Square *newsq;
  174. register Piece *newp;
  175. WORD ocol, orow;
  176. WORD x;
  177.  
  178. m.dx = ncol - p->column;
  179. m.dy = nrow - p->row;
  180. if (!possible_move(p, &m, 1))
  181.     {
  182.     return(NULL);
  183.     }
  184. if ((mpt = clone_structure(&m, sizeof(m))) == NULL)
  185.     return(NULL);
  186. if (!board_move(mpt))
  187.     {
  188.     freemem(mpt);
  189.     return(NULL);
  190.     }
  191. return(mpt);
  192. }
  193.  
  194. move_piece(p, ncol, nrow)
  195. register Piece *p;
  196. WORD ncol, nrow;
  197. {
  198. struct move *m;
  199. WORD ocol, orow;
  200.  
  201. orow = p->row;
  202. ocol = p->column;
  203. if ((m = make_legal_move(p, ncol, nrow)) != NULL)
  204.     {
  205.     hide_mouse();
  206.     draw_square(&board[orow][ocol]);
  207.     draw_square(&board[nrow][ncol]);
  208.     if (m->flags & MCASTLING)
  209.         {
  210.         if (ncol == 1)    /* king's side */
  211.             {
  212.             draw_square(&board[orow][0]);    /* erase old rook */
  213.             draw_square(&board[orow][2]);    /* draw new rook */
  214.             }
  215.         else
  216.             {
  217.             draw_square(&board[orow][7]);    /* erase old rook */
  218.             draw_square(&board[orow][4]);    /* draw new rook */
  219.             }
  220.         }
  221.     if (m->flags & MENPASSANT)
  222.         {
  223.         draw_psquare(m->took_piece);
  224.         }
  225.     show_mouse();
  226.     return(1);
  227.     }
  228. return(0);
  229. }
  230.  
  231.  
  232. check_pawn(p, m)
  233. register Piece *p;
  234. register struct move *m;
  235. {
  236. if (c_pawn(p, m))
  237.     {
  238.     if (kings_row[1-p->color] == p->row + m->dy)
  239.         {
  240.         m->flags |= MQUEENING;
  241.         }
  242.     return(1);
  243.     }
  244. else
  245.     return(0);
  246. }
  247.  
  248. /* c_pawn() - check everything about pawn except promotion */
  249. c_pawn(p, m)
  250. register Piece *p;
  251. register struct move *m;
  252. {
  253. Square *os;
  254. Piece *op;
  255. WORD newcol, newrow;
  256. struct move *enm;
  257. register WORD dx, dy;
  258.  
  259. dx = m->dx;
  260. dy = m->dy;
  261. newcol = p->column + dx;
  262. newrow = p->row + dy;
  263. /* if black invert y position */
  264. if (p->color)
  265.     dy = -dy;
  266. /* now return 0 unless moving one or two pieces forward */
  267. if (dy <= 0 || dy > 2 || dx > 1 || dx < -1)
  268.     return(0);
  269. if (dy == 2)
  270.     {
  271.     if (dx != 0)    /* make sure no diagonal move with 2 forward */
  272.         return(0);
  273.     if (p->color == WHITE)
  274.         {
  275.         if (p->row != 1)
  276.             return(0);
  277.         os = &board[2][newcol];
  278.         }
  279.     else
  280.         {
  281.         if (p->row != 6)
  282.             return(0);
  283.         os = &(board[5][newcol]);
  284.         }
  285.     if (os->piece != NULL)
  286.         return(0);
  287.     }
  288. /* moving on a diagonal */
  289. os = &(board[newrow][newcol]);
  290. op = os->piece;
  291. if (dx == 0)
  292.     {
  293.     return(op == NULL);
  294.     }
  295. if (op != NULL)
  296.     return(1);
  297. /* have to check for en-passent */
  298. if (newrow != enp_row[p->color])
  299.     return(0);
  300. os = &(board[p->row][newcol]);
  301. op = os->piece;
  302. if (op == NULL)
  303.     return(0);
  304. if (op->color == p->color)
  305.     return(0);
  306. enm = history[move_count-1];
  307. if (enm->dx != 0)
  308.     return(0);
  309. if (enm->dy != -2 && enm->dy != 2)
  310.     return(0);
  311. if (enm->piece != op)
  312.     return(0);
  313. m->flags |= (MENPASSANT|MTAKING);
  314. m->took_piece = op;
  315. return(1);
  316. }
  317.  
  318. check_knight(p,m)
  319. Piece *p;
  320. Move *m;
  321. {
  322. register WORD dx, dy;
  323.  
  324. dx = m->dx;
  325. dy = m->dy;
  326. if (dx < 0)
  327.     dx = -dx;
  328. if (dy < 0)
  329.     dy = -dy;
  330. if (dx == 2 && dy == 1)
  331.     return(1);
  332. if (dx == 1 && dy == 2)
  333.     return(1);
  334. return(0);
  335. }
  336.  
  337. check_br(p, dx, dy, rook)
  338. register Piece *p;
  339. register WORD dx, dy;
  340. WORD rook;
  341. {
  342. register WORD incx, incy;
  343. WORD count;
  344. WORD cx, cy;
  345.  
  346. cx = p->column;
  347. cy = p->row;
  348. incx = incy = 1;
  349. if (dx < 0)
  350.     {
  351.     dx = -dx;
  352.     incx = -1;
  353.     }
  354. if (dy < 0)
  355.     {
  356.     dy = -dy;
  357.     incy = -1;
  358.     }
  359. count = dx;
  360. if (rook)
  361.     {
  362.     if (dx != 0 && dy != 0)
  363.         return(0);
  364.     if (dx == 0)
  365.         {
  366.         incx = 0;
  367.         count = dy;
  368.         }
  369.     else
  370.         {
  371.         incy = 0;
  372.         }
  373.     }
  374. else
  375.     {
  376.     if (dx != dy)
  377.         return(0);
  378.     }
  379. count -= 1;    /* don't have to check starting or ending positions */
  380. while (--count >= 0)
  381.     {
  382.     cx += incx;
  383.     cy += incy;
  384.     if (board[cy][cx].piece)
  385.         return(0);
  386.     }
  387. return(1);
  388. }
  389.  
  390. check_bishop(p, m)
  391. Piece *p;
  392. Move *m;
  393. {
  394. return(check_br(p, m->dx, m->dy, 0));
  395. }
  396.  
  397. check_rook(p, m)
  398. Piece *p;
  399. Move *m;
  400. {
  401. return(check_br(p, m->dx, m->dy, 1));
  402. }
  403.  
  404. check_queen(p, m)
  405. Piece *p;
  406. Move *m;
  407. {
  408. return(check_br(p, m->dx, m->dy, 0) || check_br(p, m->dx, m->dy, 1));
  409. }
  410.  
  411. check_king(p, m)
  412. Piece *p;
  413. Move *m;
  414. {
  415. register WORD dx, dy;
  416.  
  417. dx = m->dx;
  418. dy = m->dy;
  419. if (dy == 0)
  420.     {
  421.     if (dx == 2)
  422.         {
  423.         if (p->move_count != 0)    /* has king moved ? */
  424.             return(0);
  425.         p += 4;
  426.         if (p->move_count != 0)    /* has rook moved ? */
  427.             return(0);
  428.         if (check_br(p, -3, 0, 1))    /* check rook path clear */
  429.             {
  430.             m->flags |= MCASTLING;
  431.             return(1);
  432.             }
  433.         else
  434.             return(0);
  435.         }
  436.     if (dx == -2)
  437.         {
  438.         if (p->move_count != 0)    /* has king moved ? */
  439.             return(0);
  440.         p -= 3;
  441.         if (p->move_count != 0)    /* has rook moved ? */
  442.             return(0);
  443.         if (check_br(p, 2, 0, 1))    /* rook path clear? */
  444.             {
  445.             m->flags |= MCASTLING;
  446.             return(1);
  447.             }
  448.         else
  449.             return(0);
  450.         }
  451.     }
  452. return(dx >= -1 && dx <= 1 && dy >= -1 && dy <= 1);
  453. }
  454.  
  455. extern Piece *in_check(), *in_danger();
  456.  
  457. probable_move(p, m, showit)
  458. register struct piece *p;
  459. register struct move *m;
  460. WORD showit;
  461. {
  462. Piece *newp;
  463. Piece *ret;
  464. register int px, py;
  465. int ok;
  466. register int color;
  467.  
  468.  
  469. ok = 1;
  470. px = p->column + m->dx;
  471. py = p->row + m->dy;
  472. if (!(px >= 0 && px <= 7 && py >= 0 && py <= 7))    /* off board! */
  473.     return(0);
  474. m->flags = 0;
  475. m->piece = p;
  476. m->value = 0;
  477. color = p->color;
  478. if ((newp = board[py][px].piece) != NULL)            /* onto another piece */
  479.     {
  480.     if (newp->color == color)                    /* can't move onto self */
  481.         return(0);
  482.     else
  483.         {
  484.         m->flags |= MTAKING;
  485.         m->took_piece = newp;
  486.         }
  487.     }
  488. else
  489.     {
  490.     m->took_piece = NULL;
  491.     }
  492. if (!(*p->legal)(p, m))
  493.     return(0);
  494. if (m->flags & MQUEENING)
  495.     {
  496.     m->promotion = QUEEN_IX;    /* always a queen for now... */
  497.     }
  498. if (!board_move(m))
  499.     return(0);
  500. if ((ret = in_check(color)) != NULL)
  501.     {
  502.     m->flags |= MCHECKED;
  503.     ok = 0;
  504.     }
  505. if (showit)
  506.     {
  507.     if (ret != NULL)
  508.         {
  509.         short_message("In Check!", color+2);
  510.         flash_pieces(ret, pieces[color]+KING_IX);
  511.         }
  512.     }
  513. unboard_move(m);
  514. return(ok);
  515. }
  516.  
  517. possible_move(p, m, showit)
  518. Piece *p;
  519. Move *m;
  520. WORD showit;
  521. {
  522. int ok;
  523.  
  524. if (!probable_move(p, m, showit))
  525.     return(0);
  526. ok = ((!must_take) || (m->flags & MTAKING));
  527. if (showit)
  528.     {
  529.     if (!ok)
  530.         {
  531.         short_message("Must Take", p->color+2);
  532.         flash_taking_moves();
  533.         }
  534.     else if (m->flags & MQUEENING)
  535.         {
  536.         short_message("Queening!", p->color+2);
  537.         flash_color(0x407);
  538.         wait_a_jiffy(30);
  539.         }
  540.     else if (m->flags & MENPASSANT)
  541.         {
  542.         short_message("En Passent", p->color+2);
  543.         flash_color(0x007);
  544.         wait_a_jiffy(30);
  545.         }
  546.     }
  547. return(ok);
  548. }
  549.  
  550.  
  551. Piece *
  552. in_check(color)
  553. WORD color;
  554. {
  555. if (living[color] == 1)    /* last piece left it's ok */
  556.     return(NULL);
  557. return(in_danger( pieces[color]+KING_IX) );
  558. }
  559.  
  560. Piece *
  561. in_danger(king)
  562. register Piece *king;
  563. {
  564. WORD color;
  565. register Piece *p;
  566. register WORD i;
  567. struct move m;
  568.  
  569. if (king->flags & PDEAD)
  570.     return(-1);
  571. p = pieces[1-king->color];
  572. for (i=0; i<16; i++)
  573.     {
  574.     m.dx = king->column-p->column;
  575.     m.dy = king->row - p->row;
  576.     if (!(p->flags & PDEAD))
  577.         {
  578.         if ((*p->legal)(p, &m))
  579.             return(p);
  580.         }
  581.     p++;
  582.     }
  583. return(NULL);
  584. }
  585.